# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2022/1/16 23:04
# @Author : Wang Zhixing
# @File : FileVector.py
# @Software: PyCharm
import json
import numpy
import numpy as np
import os

import json
import os

import numpy
import numpy as np
from ..PrintFormat.ColorPrint import *
import networkx as nx
import shutil

'''
讲符号聚类到文件上
'''


class FileSymbolVector:
    def __init__(self, root):
        self.project = os.path.join(root, "raw")
        # 1、输出符号边上的节点总数
        edge_file = os.path.join(self.project, "symboldep.mdg")
        edge = self._node(edge_file)
        RedPrint("symbol.mdg节点的数量：" + str(len(edge)))
        # 2、从vector中读出我们的符号的vector
        f = os.path.join(self.project, "symbolvectors.txt")
        self.symbol_vector, self.vector_dimension = self.ReadVector(f)
        RedPrint("符号vector的数量：" + str(len(self.symbol_vector)))
        RedPrint("符号vector的维度：" + str(self.vector_dimension))

    def remove_noedge_node(self):
        tmp = []
        for node in self.symbol_vector.keys():
            if str(node) not in self.sub.nodes:
                tmp.append(node)

        for t in tmp:
            self.symbol_vector.pop(t)

    def getsymbolanddimension(self):
        return self.symbol_vector, self.vector_dimension

    def ReadVector(self, file):
        Symbol2Vector = {}
        with open(file, "r") as VectorFile:
            VectorLine = VectorFile.readlines()
            for Vector in VectorLine:
                Vectorid = int(Vector.split(" ")[0])
                vector = []
                for num in Vector.split(" ")[1:]:
                    vector.append(float(num))
                Symbol2Vector[Vectorid] = vector
                vectordimension = len(vector)
        return Symbol2Vector, vectordimension

    def _node(self, file):
        node = []
        with open(file, "r") as edgesfile:
            edges = edgesfile.readlines()
            for edge in edges:
                inedge = int(edge.split()[0])
                outedge = int(edge.split()[1])
                if inedge not in node:
                    node.append(inedge)
                if outedge not in node:
                    node.append(outedge)
        return node

    def miss(self, all, nodeveclist):
        miss1 = []
        miss2 = []
        for i in all:
            if i not in nodeveclist:
                miss1.append(i)
        for i in nodeveclist:
            if i not in all:
                miss2.append(i)
        return miss1, miss2

    def ListOfOutEdgeNode(self, file):
        outedges = {}
        with open(file, "r") as edgesfile:
            edges = edgesfile.readlines()
            for edge in edges:
                inedge = int(edge.split()[0])
                outedge = int(edge.split()[1])
                weight = int(edge.split()[2])
                if inedge not in outedges:
                    outedges[inedge] = [outedge]
                else:
                    outedges[inedge].append(outedge)
        return outedges

    def ListOfNoVectorNode(self, misses, out, vector):
        no_out_edge = []
        outedge_has_vector = []
        for miss in misses:
            if miss not in out:
                no_out_edge.append(miss)  # 没有出边的节点
            else:
                for outedge in out[miss]:
                    if outedge in vector:
                        outedge_has_vector.append(miss)
                        break
        return no_out_edge, outedge_has_vector

    def ReBuildEdge(self, fin, miss, no_out_edge, outedge_has_vector, fout):
        with open(fin, "r") as edgesfile:
            with open(fout, "w") as rebuild_edgefile:
                edges = edgesfile.readlines()
                for edge in edges:
                    inedge = int(edge.split()[0])
                    outedge = int(edge.split()[1])
                    if inedge not in miss and outedge not in miss:
                        rebuild_edgefile.write(str(inedge) + " " + str(outedge) + " 1\n")
                    elif inedge not in no_out_edge and outedge not in no_out_edge:
                        if inedge in outedge_has_vector and outedge in outedge_has_vector:
                            rebuild_edgefile.write(str(inedge) + " " + str(outedge) + " 1\n")
        ##################################################

        G = nx.DiGraph()
        with open(fout, "r")as fp:
            lines = fp.readlines()
            for line in lines:
                line = line.split("\n")[0]
                line = line.split()
                G.add_edge(line[0], line[1])
        self.H = G.to_undirected()
        RedPrint("最大的含有vector节点数" + str(len(self.H.nodes)))
        os.remove(fout)
        with open(fout, "w")as fp:
            for c in nx.connected_components(self.H):
                if len(c) > 200:
                    self.sub = self.H.subgraph(c)
                    RedPrint("最大的子图节点数" + str(len(self.sub.nodes)))
                    for u, v in self.sub.edges:
                        fp.writelines(str(u) + " " + str(v) + " 1\n")
        ################################################


class FileVector:
    def __init__(self, root):
        symbolVector = FileSymbolVector(root)
        symbol_vector, vector_dimension = symbolVector.getsymbolanddimension()
        file = os.path.join(root, 'raw', "filedefsymbol.json")
        edge_path = os.path.join(root, 'raw', "edge.rsf")
        dic = self.SymbolVector2FileVector(file, symbol_vector, edge_path, vector_dimension)
        filename = os.path.join(root, 'raw', "new_filevectors.json")
        with open(filename, 'w') as file_obj:
            json.dump(dic, file_obj)

    def SymbolVector2FileVector(self, file, vector, edge_path, vectordimension):
        dic = {}
        filedic = {}
        averagenum = 0
        hasvectorfilelist = []
        nohasvectorfilelist = []
        with open(file, 'r', encoding='utf8') as fp:
            json_data = json.load(fp)
            GreenPrint("提取的符号文件有" + str(len(json_data)) + "个")
            for file in json_data:
                ve = []
                for symbol in file['symbol']:
                    if vector.get(symbol) is not None:
                        ve.append(vector.get(symbol))
                if len(ve) != 0:
                    averagenum += 1

                    # ve = list(numpy.mean(ve, axis=0))
                    ve = list(numpy.sum(ve,axis=0))

                    dic[file['name']] = ve
                    hasvectorfilelist.append(file['name'])
                else:
                    nohasvectorfilelist.append(file['name'])
        GreenPrint("提取的符号中，包含字符的文件有" + str(averagenum) + "个")
        has_hanshu_num = 0
        no_has_hanshu =0
        all_node = 0
        list1 = []#含有vector的
        list2 = []#提取的了文件，但是文件中的函数没有初始vector
        list3 = []#没有提取到文件
        with open(edge_path, "r") as fp:
            for line in fp.readlines():
                edge_index = line.split()
                s = edge_index[1]
                t = edge_index[2]

                if s not in filedic:
                    all_node+=1
                    if s not in dic:
                        ve = list(np.ones(vectordimension))
                        filedic[s] = ve
                        no_has_hanshu+=1
                        if s in nohasvectorfilelist:
                            if s not in list2:
                                list2.append(s)
                        else:
                            if s not in list3:
                                list3.append(s)

                    else:
                        if s not in list1:
                            list1.append(s)
                        filedic[s] = dic[s]
                        has_hanshu_num+=1

                if t not in filedic:
                    all_node+=1
                    if t not in dic:
                        ve = list(np.ones(vectordimension))
                        filedic[t] = ve


                        no_has_hanshu += 1
                        if t in nohasvectorfilelist:
                            if t not in list2:
                                list2.append(t)
                        else:
                            if t not in list3:
                                list3.append(t)
                    else:
                        if t not in list1:
                            list1.append(t)
                        filedic[t] = dic[t]
                        has_hanshu_num+=1
        '''        
        delnum = 0
        edgenum = 0
        with open(edge_path, "r") as fp:
            with open(edge_path.replace("edge","edge1"),"w") as fp1 :
                for line in fp.readlines():
                    if line.split()[0] in list1 and line.split()[1] in list1:
                        fp1.writelines(line)
                        edgenum+=1
                    else:
                        delnum+=1
        print("边的数量:", edgenum)
        print("删除掉的边的数量:", delnum)
        '''

        GreenPrint("图中节点总数：" + str(all_node) + "个")
        GreenPrint("图中节点，含有初始vector：" + str(has_hanshu_num) + "个")
        GreenPrint("图中节点，初始vector为全1的：" + str(no_has_hanshu) + "个")
        print("含有vector的文件:",len(list1))
        # print(list1)
        print("提取的了文件，但是文件中的函数没有初始vector:", len(list2))
        # print(list2)
        print("没有提取到文件:", len(list3))
        # print(list3)
        return filedic
